package cn.edu.ctbu.dp01.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

@Component
@Aspect
@Slf4j // 正确的大写L
public class httpAspect {

    // 定义切入点，匹配 StudentApiController 中的所有方法
    @Pointcut("execution(* cn.edu.ctbu.dp01.api.StudentApiController.*(..))")
    public void log() {
    }

    // 在方法执行前执行
    @Before("log()")
    public void doBefore() {
        log.info("准备开始执行 API...");
    }

    // 在方法执行后执行，无论方法是否抛出异常
    @After("log()")
    public void doAfter() {
        log.info("执行 API 完成，准备返回...");
    }

    // 在方法正常执行后执行，返回值为 response
    @AfterReturning(returning = "object", pointcut = "log()")
    public void afterReturning(Object object) {
        log.info("API 返回的响应: {}", object);
    }

    // 环绕通知，计算方法的执行时间
    @Around("log()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        // 启动计时器
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        // 获取方法签名信息
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        String methodName = signature.getDeclaringTypeName() + "." + signature.getName();
        Object[] args = pjp.getArgs();

        // 打印方法开始执行的日志（包括参数）
        log.info("正在执行方法: {}，参数: {}", methodName, args);

        // 执行目标方法
        Object result = null;
        try {
            result = pjp.proceed(args);  // 执行目标方法
        } catch (Throwable e) {
            log.error("执行方法 {} 时发生异常: {}", methodName, e.getMessage());
            throw e; // 如果有异常，继续抛出
        } finally {
            // 停止计时
            stopWatch.stop();
            long cost = stopWatch.getTotalTimeMillis();

            // 输出方法执行时间
            log.info("方法 {} 执行完毕，用时: {} ms", methodName, cost);

            // 输出返回结果
            log.info("API 返回结果: {}", result);
        }

        return result;
    }
}
